package namespace

import (
	"time"

	"gddgame.cc/galaxy/binocle"
	. "gddgame.cc/galaxy/common/dsl/game"
	"gddgame.cc/galaxy/common/namespaces"
	"gddgame.cc/galaxy/common/service/lobby"
	"gddgame.cc/galaxy/common/service/lobby/pve"
	"gddgame.cc/galaxy/common/service/playbook"
	"gddgame.cc/galaxy/core/models"
	"gddgame.cc/galaxy/core/sdk"
	"gddgame.cc/galaxy/project/star/star/controller"
	"gddgame.cc/galaxy/project/star/star/model"
	"gddgame.cc/galaxy/satellite/formula/nebula"
	"gddgame.cc/galaxy/server/composer"
	"gddgame.cc/galaxy/utils/def"
)

type Delegate struct {
	*sdk.AppClient
	binocle.App
	*Environment
}

func (d *Delegate) Version() string {
	return d.App.Version()
}

func (d *Delegate) GetUserId(userOpen *models.UserOpen) (int, error) {
	var user model.User
	create, err := controller.Center.FindOrCreateUser(userOpen.Id, &user, func() {
		// 新用户，创建用户数据
		user.OpenId = userOpen.Id
		user.Level = 1
		user.Grade = 1
		user.BaseId = model.DefaultBaseId
		user.Entity = model.DefaultEntity
	})
	if err != nil {
		return 0, err
	}
	if create {
		if err := controller.InitUser(d.Environment.Context(), &user); err != nil {
			return 0, err
		}
	}
	return user.Id, nil
}
func (d *Delegate) Connect(context def.Context, userOpen *models.UserOpen, userId int) {
	_ = controller.Env.RefreshUserStatus(userOpen.Id, false)

	// 登录清空缓存
	_ = controller.Center.CleanUser(userId)
	var user model.User
	if err := controller.Center.GetUser(userId, &user); err != nil {
		return
	}
	if userOpen.LastTime == nil {
		// 第一次登录
		_ = controller.Center.UpdateStatSingle(context, &user, controller.Center.StatData, model.CurrentLogin, 1, false)
		_ = controller.Center.UpdateStatSingle(context, &user, controller.Center.StatData, model.MaxLogin, 1, false)
		return
	}
	// 更新用户语言设置
	language := GetLanguage(context)
	_ = controller.Env.UpdateUserStatus(userOpen.Id, LanguageKey, language)

	location := GetZone(context)
	local := userOpen.LastTime.In(location)
	now := time.Now()
	if local.YearDay() == now.YearDay() {
		// 如果最后一次登录在今天，不统计
		return
	}
	next := local.AddDate(0, 0, 1)
	if next.Day() == now.Day() {
		// 最后一次登录是昨天，连续登录天数+1
		_ = controller.Center.UpdateStatSingle(context, &user, controller.Center.StatData, model.CurrentLogin, 1, false)
		// 更新最大连续登录天数
		_ = controller.Center.UpdateStatSingle(context, &user, controller.Center.StatData, model.MaxLogin, 1, false)
		// 更新登录徽章
		//_ = controller.UpdateBadgeSingle(context, user, model.LoginBadge)
	} else {
		// 最后一次登录大于1天，清空连续登录天数
		_ = controller.Center.UpdateStatSingle(context, &user, controller.Center.StatData, model.CurrentLogin, 1, true)
	}
}
func (d *Delegate) Disconnect(context def.Context, openId string, userId int) {
	_ = controller.Env.RefreshUserStatus(openId, false)
}

func (d *Delegate) SendSharedMessage(userOpen *models.UserOpen, userId int, targetId string) error {
	var user model.User
	if err := controller.Center.FindUser(targetId, &user); err != nil {
		return err
	}
	// 添加分享奖励
	// 给发送分享的人发送
	if _, err := controller.SendShareMessage(d.Environment.Context(), user.Id, userOpen.Id, userOpen.NickName); err != nil {
		return err
	}
	// 给加入人发送
	return nil
}

func (d *Delegate) StartPlay(instance *namespaces.RoomInstance) error {
	pb, err := controller.StartPlaybook(d.AppClient, d.App, instance)
	if err != nil {
		return err
	}
	instance.RoomInstanceDelegate = pb
	pb.OnStart(func(players []*playbook.Player) {
		instance.OnStart()
	})
	pb.OnProcess(func(member string, data []byte) {
		instance.OnProcess(member, data)
	})
	return nil
}

func (d *Delegate) GetAccessTokenPolicy(namespace string, token string) map[string]interface{} {
	return map[string]interface{}{
		"orbit.sync:type": "single",
		"orbit.sync:rate": 50, // 服务器加快下发速度
		"orbit.sync:gap":  0,
	}
}

func InitHandler(builder composer.Builder, client *sdk.AppClient, handler nebula.NamespaceHandler) error {
	var agent binocle.App
	builder.Factory("agent", &agent)
	delegate := &Delegate{AppClient: client, App: agent, Environment: controller.Env}

	// 匹配服务
	lobbyServer := lobby.Default()
	lobbyServer.RegisterMatch(pve.Default)

	controller.Env.AuthManager = namespaces.AuthHandler(builder, handler(AUTH), client, delegate)
	controller.Env.SceneManager = namespaces.SceneHandler(builder, handler(SCENE), client, delegate)
	controller.Env.RoomManager = namespaces.RoomHandler(builder, handler(ROOM), client, delegate)
	controller.Env.TeamManager = namespaces.TeamHandler(builder, handler(TEAM), client, delegate)

	// todo 兼容写法
	InfoHandler(builder, client, handler(4))
	InfoHandler(builder, client, handler(INFO))
	if err := delegate.AuthManager.Depends(); err != nil {
		return err
	}
	if err := delegate.SceneManager.Depends(); err != nil {
		return err
	}
	if err := delegate.RoomManager.Depends(); err != nil {
		return err
	}
	if err := delegate.TeamManager.Depends(); err != nil {
		return err
	}
	return nil
}
